package cn.sgy.infrastructure.web.xss.business.get;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

/**
 * @author sgy
 * @description 跨站攻击 过滤器
 * @date 2022/8/20
 */
@Slf4j
public class XssFilter implements Filter {
    /**
     * 保存所有要忽略的地址
     */
    private List<String> ignorePathList;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        if (log.isDebugEnabled()) {
            log.debug("XSS Filter [XSSFilter] init start ...");
        }
        String excludes = filterConfig.getInitParameter("excludes");
        if (!StrUtil.isBlank(excludes)) {
            String[] split = excludes.split(",");
            ignorePathList = Arrays.asList(split);
        }
        if (log.isDebugEnabled()) {
            log.debug("ignorePathList = [{}]", JSONUtil.toJsonStr(ignorePathList));
            log.debug("XSS Filter [XSSFilter] init end");
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        if (log.isDebugEnabled()) {
            log.debug("XSS Filter [XSSFilter] starting");
        }
        // 判断uri是否包含项目名称
        String uriPath = ((HttpServletRequest) request).getRequestURI();
        if (isIgnorePath(uriPath)) {
            if (log.isDebugEnabled()) {
                log.debug("ignore xssfilter,path[{}] pass through XssFilter, go ahead...", uriPath);
            }
            chain.doFilter(request, response);
            return;
        } else {
            if (log.isDebugEnabled()) {
                log.debug("has XssFilter path[{}] need XssFilter, go to XssRequestWrapper", uriPath);
            }
            //传入重写后的Request
            chain.doFilter(new XssRequestWrapper((HttpServletRequest) request, null), response);
        }
        if (log.isDebugEnabled()) {
            log.debug("XSS Filter [XSSFilter] stop");
        }
    }

    @Override
    public void destroy() {
        if (log.isDebugEnabled()) {
            log.debug("XSS Filter [XSSFilter] destroy");
        }
        ignorePathList = null;
    }

    /**
     * 传入给定访问地址查看是否在忽略列表中
     */
    private boolean isIgnorePath(String servletPath) {
        if (StrUtil.isBlank(servletPath)) {
            return true;
        }
        if (CollectionUtil.isEmpty(ignorePathList)) {
            return false;
        } else {
            for (String ignorePath : ignorePathList) {
                if (!StrUtil.isBlank(ignorePath) && servletPath.contains(ignorePath.trim())) {
                    return true;
                }
            }
        }
        return false;
    }
}
